/*
 * Copyright (C) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

use crate::common::constants::ErrorCode;
use crate::log_e;
use crate::traits::crypto_engine::CryptoEngineRegistry;
use crate::traits::executor_manager::{ExecutorFilter, ExecutorInfo, ExecutorManager};
use crate::{Box, Vec};
use core::mem::size_of;

pub struct DefaultExecutorManager {
    executors: Vec<ExecutorInfo>,
}

impl DefaultExecutorManager {
    pub fn new() -> Self {
        DefaultExecutorManager {
            executors: Vec::new(),
        }
    }

    fn generate_unique_executor_index(&self) -> Result<u64, ErrorCode> {
        let mut executor_index = [0u8; 8];
        let executors_vec = self.executors.clone();

        CryptoEngineRegistry::get()
            .secure_random_with_check(
                &mut executor_index,
                Box::new(move |bytes: &[u8]| {
                    if bytes.len() != size_of::<u64>() {
                        return false;
                    }
                    let index = u64::from_ne_bytes(bytes.try_into().unwrap());
                    !executors_vec.iter().any(|e| e.executor_index == index)
                }),
            )
            .map_err(|_| ErrorCode::GeneralError)?;

        Ok(u64::from_ne_bytes(executor_index))
    }
}

impl ExecutorManager for DefaultExecutorManager {
    fn register(&mut self, executor_info: &ExecutorInfo) -> Result<u64, ErrorCode> {
        let mut new_executor = executor_info.clone();
        if let Some((index, old_executor)) = self
            .executors
            .iter_mut()
            .enumerate()
            .find(|(_, x)| x.get_key() == new_executor.get_key())
        {
            new_executor.executor_index = old_executor.executor_index;
            self.executors.remove(index);
        } else {
            new_executor.executor_index = self.generate_unique_executor_index()?;
        }

        let new_executor_index = new_executor.executor_index;
        self.executors.push(new_executor);
        Ok(new_executor_index)
    }

    fn unregister(&mut self, executor_index: u64) {
        let before_len = self.executors.len();
        self.executors
            .retain(|e| e.executor_index != executor_index);
        if before_len == self.executors.len() {
            log_e!("invalid executor index");
        }
    }

    fn get_executor(&self, filter: ExecutorFilter) -> Result<ExecutorInfo, ErrorCode> {
        let executors = self.get_executor_list(filter);
        if executors.len() == 1 {
            Ok(executors.get(0).cloned().ok_or(ErrorCode::GeneralError)?)
        } else {
            log_e!("failed to get executor, executor num {}", executors.len());
            Err(ErrorCode::NotFound)
        }
    }

    fn get_executor_list(&self, filter: ExecutorFilter) -> Vec<ExecutorInfo> {
        self.executors
            .iter()
            .filter(|e| filter(e))
            .cloned()
            .collect()
    }

    fn get_executor_matcher(&self, filter: ExecutorFilter) -> Result<u32, ErrorCode> {
        let executor_info = self.get_executor(filter)?;
        Ok(executor_info.matcher)
    }

    fn get_min_esl(&mut self, executor_info_list: &Vec<ExecutorInfo>) -> Result<u32, ErrorCode> {
        if executor_info_list.is_empty() {
            log_e!("executor_info_list is empty");
            return Err(ErrorCode::BadParam);
        }

        let min_esl = executor_info_list
            .iter()
            .map(|info| info.esl as u32)
            .min()
            .ok_or_else(|| {
                log_e!("failed to find min esl");
                ErrorCode::GeneralError
            })?;
        Ok(min_esl)
    }
}
